/*--------------------------------------------------------------------------------
 * Adaptive Intelligence - Windows Forms Controls Class Library
 * Version 2.00
 * 
 * Advanced Image Box Control Class
 *      Provides an image display mechanism with optional auto-shadowing capability.
 *------------------------------------------------------------------------------*/

/*--------------------------------------------------------------------------------
 * System Imports
 *------------------------------------------------------------------------------*/
using System;
using System.Text;
using System.ComponentModel;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Windows.Forms;

namespace Adaptive.Foundation.Windows.Forms
{
    /// <summary>
    /// Provides an image display mechanism with optional auto-shadowing capability.
    /// </summary>
    [ToolboxBitmap(typeof(EmbeddedResourceFinder), "Adaptive.Foundation.Windows.Forms.AdvancedImageBox.bmp")]
    public partial class AdvancedImageBox : AdaptiveControlBase
    {
        /*--------------------------------------------------------------------------------
         * Public Event Definitions
         *------------------------------------------------------------------------------*/
        #region Public Event Definitions
        #endregion

        /*--------------------------------------------------------------------------------
         * Private Constants Declarations
         *------------------------------------------------------------------------------*/
        #region Private Constants Declarations
        #endregion

        /*--------------------------------------------------------------------------------
         * Private Member Declarations
         *------------------------------------------------------------------------------*/
        #region Private Member Declarations
        /// <summary>
        /// Image to be displayed.
        /// </summary>
        private Image _image;
        /// <summary>
        /// Behave as a button flag.
        /// </summary>
        private bool _click = false;
        /// <summary>
        /// Mouse-is-down flag.
        /// </summary>
        private bool _mouseDown = false;
        /// <summary>
        /// Image magnification level.
        /// </summary>
        private int _magnification = 1;
        #endregion

        /*--------------------------------------------------------------------------------
         * Constructor / Dispose / Destructor Methods
         *------------------------------------------------------------------------------*/
        #region Constructor / Dispose / Destructor Methods
        /// <summary>
        /// Initializes a new instance of the class.
        /// </summary>
        /// <remarks>
        /// This is the default constructor.
        /// </remarks>
        public AdvancedImageBox()
            : base()
        {
            SetStyle(ControlStyles.SupportsTransparentBackColor, true);
            SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            SetStyle(ControlStyles.DoubleBuffer, true);
            SetStyle(ControlStyles.UserPaint, true);

            //This call is required by the Windows Form Designer.
            InitializeComponent();
        }
        /// <summary>
        /// Deallocates internally allocated objects.
        /// </summary>
        /// <param name="disposing">
        /// A value indicating whether the object is being disposed.
        /// </param>
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (components != null)
                    components.Dispose();

                if (_image != null)
                    _image.Dispose();
            }

            _image = null;
            components = null;
            base.Dispose(disposing);
        }
        #endregion

        /*---------------------------------------------------------------------------
		 * Hidden Properties
		 *-------------------------------------------------------------------------*/
        #region Hidden Properties
        [Browsable(false)]
        internal new string Text
        {
            get { return string.Empty; }
            set { base.Text = string.Empty; }
        }
        #endregion

        /*--------------------------------------------------------------------------------
         * Public Properties
         *------------------------------------------------------------------------------*/
        #region Public Properties
        /// <summary>
        /// Gets or sets the Image that will be displayed.
        /// </summary>
        /// <value>
        /// An <see cref="Image"/> to be displayed.
        /// </value>
        [Browsable(true), Category("Appearance"),
        Description("Gets or sets the Image that will be displayed.")]
        public Image Image
        {
            get { return _image; }
            set
            {
                _image = value;
                Invalidate();
            }
        }
        /// <summary>
        /// Gets or sets a value indicating whether the image will act as a button.
        /// </summary>
        /// <value>
        /// <b>true</b> if the image is clickable and modifies the shadow according
        /// to the mouse events; otherwise, <b>false</b>.
        /// </value>
        /// <remarks>
        /// If this value is <b>true</b>, the normal shadowed image loses its shadow
        /// and is shifted slightly down and right on the <see cref="System.Windows.Forms.Control.MouseDown"/> event.
        /// The image is restored on the <see cref="System.Windows.Forms.Control.MouseUp"/> event.
        /// </remarks>
        [Browsable(true), Category("Interaction"), DefaultValue(false),
        Description("Gets or sets a value indicating whether the image will act as a button.")]
        public bool Clickable
        {
            get { return _click; }
            set { _click = value; }
        }
        /// <summary>
        /// Gets or sets the image magnification value.
        /// </summary>
        /// <value>
        /// A magnification factor.
        /// </value>
        [Browsable(true), Category("Appearance"), DefaultValue(1),
         Description("Gets or sets the magnification value for the image.")]
        public int Magnification
        {
            get { return _magnification; }
            set
            {
                if (value >= 1)
                    _magnification = value;
                Invalidate();
            }
        }
        #endregion

        /*--------------------------------------------------------------------------------
         * Protected Methods / Event Methods
         *------------------------------------------------------------------------------*/
        #region Protected Methods / Event Methods
        /// <summary>
        /// Raises the <see cref="Control.Resize"/> event.
        /// </summary>
        /// <param name="e">
        /// An <see cref="EventArgs"/> event arguments instance.
        /// </param>
        protected override void OnResize(EventArgs e)
        {
            if (Visible)
            {
                if (_image != null)
                    Invalidate();
            }
        }
        /// <summary>
        /// Raises the <see cref="Control.Paint"/> event.
        /// </summary>
        /// <param name="e">
        /// A <see cref="PaintEventArgs"/> event arguments instance containing
        /// the <see cref="Graphics"/> instance used to perform drawing tasks.
        /// </param>
        protected override void OnPaint(PaintEventArgs e)
        {
            if (Visible)
            {
                if (_image != null)
                    Render(e.Graphics);
            }
            base.OnPaint(e);
        }
        /// <summary>
        /// Raises the <see cref="Control.MouseDown"/> event.
        /// </summary>
        /// <param name="e">
        /// An <see cref="MouseEventArgs"/> event arguments instance 
        /// indicating the mouse position.
        /// </param>
        protected override void OnMouseDown(MouseEventArgs e)
        {
            if (_click)
                _mouseDown = true;
            Invalidate();

            base.OnMouseDown(e);

        }
        /// <summary>
        /// Raises the <see cref="Control.MouseUp"/> event.
        /// </summary>
        /// <param name="e">
        /// An <see cref="MouseEventArgs"/> event arguments instance.
        /// indicating the mouse position.
        /// </param>
        protected override void OnMouseUp(MouseEventArgs e)
        {
            if (_click)
            {
                _mouseDown = false;
                Invalidate();
            }
            base.OnMouseUp(e);
        }
        /// <summary>
        /// Creates and assigns the event handlers for the items contained within the control.
        /// </summary>
        protected override void AssignEventHandlers()
        {
        }
        /// <summary>
        /// Removes the event handlers for the items contained within the control.
        /// </summary>
        protected override void RemoveEventHandlers()
        {
        }
        /// <summary>
        /// Initializes the content of the control before the event handlers are assigned.
        /// </summary>
        protected override void InitializeContent()
        {
        }
        /// <summary>
        /// This method is invoked in the main UI thread to perform any neccessary
        /// updates to the UI.
        /// </summary>
        /// <remarks>
        /// Calling the related <see cref="AdaptiveControlBase.UpdateControl()"/> is used to prevent illegal 
        /// cross-threaded UI update calls.
        /// </remarks>
        protected override void UpdateCurrentControlContents()
        {
            Invalidate();
            Refresh();
        }
        /// <summary>
        /// This method is invoked in the main UI thread to perform any neccessary
        /// updates to the UI.
        /// </summary>
        /// <remarks>
        /// Calling the related <see cref="AdaptiveControlBase.UpdateControl(object[])"/> is used to prevent illegal 
        /// cross-threaded UI update calls.
        /// </remarks>
        /// <param name="data">
        /// The data supplied to the control to update the internal controls with.
        /// </param>
        protected override void UpdateCurrentControlContents(object[] data)
        {
            Invalidate();
            Refresh();
        }
        #endregion

        /*--------------------------------------------------------------------------------
         * Public Methods / Functions
         *------------------------------------------------------------------------------*/
        #region Public Methods / Functions
        /// <summary>
        /// Gets the color at the specified bitmap position.
        /// </summary>
        /// <param name="x">The x-co-ordinate.</param>
        /// <param name="y">The y-co-ordinate.</param>
        /// <returns>
        /// The <see cref="Color"/> at the specified position.
        /// </returns>
        public Color GetColor(int x, int y)
        {
            Bitmap bitmap = null;
            Color returnValue = Color.White;

            if (_image != null)
            {
                bitmap = new Bitmap(_image);
                if (_magnification > 1)
                {
                    x = (int)((float)x / _magnification);
                    y = (int)((float)y / _magnification);
                }
                returnValue = bitmap.GetPixel(x, y);
                bitmap.Dispose();
            }

            bitmap = null;
            return returnValue;
        }
        #endregion

        /*--------------------------------------------------------------------------------
         * Private Event Handlers
         *------------------------------------------------------------------------------*/
        #region Private Event Handlers
        #endregion

        /*--------------------------------------------------------------------------------
         * Private Methods / Functions
         *------------------------------------------------------------------------------*/
        #region Private Methods / Functions
        /// <summary>
        /// Draws the image into the control.
        /// </summary>
        /// <param name="g">
        /// A <see cref="Graphics"/> instance used to perform the drawing tasks.
        /// </param>
        private void Render(Graphics g)
        {
            Bitmap shadowA = null;
            Bitmap shadowB = null;
            Color colorA;
            Color colorB;
            RectangleF point;
            Rectangle rect;
            int width = 0;
            int height = 0;

            if (_image.Width > Width)
                width = Width;
            else
                width = _image.Width;
            if (_image.Height > Height)
                height = Height;
            else
                height = _image.Height;

            try
            {
                colorA = Color.FromArgb(100, SystemColors.ControlDark.R, SystemColors.ControlDark.G, SystemColors.ControlDark.B);
                colorB = Color.FromArgb(80, SystemColors.ControlDark.R, SystemColors.ControlDark.G, SystemColors.ControlDark.B);
                shadowA = GraphicsTasks.ShadowImage(_image, colorA);
                shadowB = GraphicsTasks.ShadowImage(_image, colorB);

                if (_magnification == 1)
                {
                    if ((_click) && (_mouseDown))
                    {

                        point = new RectangleF(1, 1, width, height);
                        g.DrawImage(_image, point);
                    }
                    else
                    {
                        point = new RectangleF(2, 3, width, height);
                        g.DrawImage(shadowB, point);
                        g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                        point = new RectangleF(1, 2, width, height);
                        g.DrawImage(shadowA, point);
                        point = new RectangleF(0, 0, width, height);
                        g.DrawImage(_image, point);
                    }
                }
                else
                {

                    rect = new Rectangle(0, 0, _image.Width * _magnification, _image.Height * _magnification);
                    g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.AssumeLinear;
                    g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None;
                    g.DrawImage(_image, rect);
                }

                shadowA.Dispose();
                shadowB.Dispose();
                shadowA = null;
                shadowB = null;
            }
            catch
            { }
        }
        #endregion

    }
}
